package com.attendance.www.hr.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import com.attendance.www.hr.beans.ApprovalRecordBean;
import com.attendance.www.hr.beans.RetroactiveBean;
import com.attendance.www.hr.beans.RetroactivePageBean;
import com.attendance.www.hr.dao.mapper.ApprovalRecordExtMapper;
import com.attendance.www.hr.dao.mapper.ApprovalRecordMapper;
import com.attendance.www.hr.dao.mapper.ApprovalRuleMapper;
import com.attendance.www.hr.dao.mapper.AttendanceMapper;
import com.attendance.www.hr.dao.mapper.CorporationMapper;
import com.attendance.www.hr.dao.mapper.EmployeeCorporationMapper;
import com.attendance.www.hr.dao.mapper.EmployeeMapper;
import com.attendance.www.hr.dao.mapper.EmployeeRoleMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSchedulMapper;
import com.attendance.www.hr.dao.mapper.PunchTimeMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveExtMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveMapper;
import com.attendance.www.hr.dao.mapper.RoleMapper;
import com.attendance.www.hr.dao.mapper.SchedulDayMapper;
import com.attendance.www.hr.entitys.ApprovalRecord;
import com.attendance.www.hr.entitys.ApprovalRule;
import com.attendance.www.hr.entitys.ApprovalRuleExample;
import com.attendance.www.hr.entitys.Attendance;
import com.attendance.www.hr.entitys.AttendanceExample;
import com.attendance.www.hr.entitys.Corporation;
import com.attendance.www.hr.entitys.Employee;
import com.attendance.www.hr.entitys.EmployeeCorporation;
import com.attendance.www.hr.entitys.EmployeeCorporationExample;
import com.attendance.www.hr.entitys.EmployeeExample;
import com.attendance.www.hr.entitys.EmployeeRole;
import com.attendance.www.hr.entitys.EmployeeRoleExample;
import com.attendance.www.hr.entitys.EmployeeSchedul;
import com.attendance.www.hr.entitys.EmployeeSchedulExample;
import com.attendance.www.hr.entitys.PunchTime;
import com.attendance.www.hr.entitys.Retroactive;
import com.attendance.www.hr.entitys.RetroactiveExample;
import com.attendance.www.hr.entitys.Role;
import com.attendance.www.hr.entitys.RoleExample;
import com.attendance.www.hr.entitys.SchedulDayExample;
import com.attendance.www.hr.entitys.SchedulDayKey;
import com.attendance.www.hr.exception.ResultFaultException;
import com.attendance.www.hr.service.IApprovalService;
import com.attendance.www.hr.service.IBpmService;
import com.attendance.www.hr.service.IRetroactiveService;

@Service
public class RetroactiveServiceImpl implements IRetroactiveService {

	@Resource
	private RetroactiveMapper retroactiveDao;
	@Resource
	private RetroactiveExtMapper retroactiveExtDao;
	@Resource
	private AttendanceMapper attendanceDao;
	@Resource
	private ApprovalRecordExtMapper ApprovalRecordExtDao;
	@Resource
	private RoleMapper roleDao;
	@Resource
	private ApprovalRuleMapper approvalRuleDao;
	@Resource
	private ApprovalRecordMapper approvalRecordDao;
	@Resource
	private EmployeeRoleMapper employeeRoleDao;
	@Resource
	private EmployeeMapper employeeDao;
	@Resource
	private EmployeeCorporationMapper employeeCorporationDao;
	@Resource
	private CorporationMapper corporationDao;
	@Resource
	private EmployeeSchedulMapper employeeSchedulDao;
	@Resource
	private SchedulDayMapper schedulDayDao;
	@Resource
	private PunchTimeMapper punchTimeDao;
	@Resource
	private IApprovalService approvalService;
	@Resource
	private IBpmService bpmService;
	
	/**
	 * 新增考勤补签
	 */
	@Override
	public boolean saveRetroactive(RetroactiveBean retroactiveBean,Integer employeeId) {
		//验证补签是否重复
		if (retroactiveBean.getZeroDegree() != null && retroactiveBean.getZeroDegree() == 0) {//不计补签次数
			//跨天补签，不计次数，不验证重复
		} else {
			if (this.verifyRetroactive(retroactiveBean, employeeId)) {
				throw new ResultFaultException("2_00003");
			}
		}
		
		//申请人岗位
		Role requestRole = roleDao.selectByPrimaryKey(retroactiveBean.getRoleId());
		//获取审批规则
		ApprovalRule approvalRule = getApprovalRule(requestRole);
		if (approvalRule==null) {
			throw new ResultFaultException("10_00001");
		}
		//新增补签记录
		Retroactive retroactive=new Retroactive();
		retroactive.setAttendanceId(retroactiveBean.getAttendanceId());
		retroactive.setEmployeeId(employeeId);
		retroactive.setRetroactiveDate(new Date());
		retroactive.setDescription(retroactiveBean.getDescription());
		Integer count=0;
		if (StringUtils.isNotBlank(retroactiveBean.getStartTime())) {
			retroactive.setStartTime(retroactiveBean.getStartTime());
			count++;
		}
		if (StringUtils.isNotBlank(retroactiveBean.getEndTime())) {
			retroactive.setEndTime(retroactiveBean.getEndTime());
			count++;
		}
		if (retroactiveBean.getZeroDegree() != null && retroactiveBean.getZeroDegree() == 0) {//不计补签次数
			retroactive.setRetroactiveNumber(0);
		} else {
			retroactive.setRetroactiveNumber(count);
		}
		
		retroactive.setApprovalState(1);//直接写死，1审批中
		retroactive.setApprovalRuleId(approvalRule.getApprovalRuleId());
		int record=retroactiveDao.insertSelective(retroactive);
		if(record<=0){
			return false;
		}
		
		Integer attendanceId=retroactiveBean.getAttendanceId();
		Attendance attendance=new Attendance();
		attendance.setAttendanceId(attendanceId);
		//考勤记录，设置为审批中，补签中。
		attendance.setIsApprovaled(1);
		attendance.setIsRepaired(1);
		attendanceDao.updateByPrimaryKeySelective(attendance);
		
		/**
		 * 增加一条审批记录，补签是直接提交，取得申请人的岗位级别
		 * 如果空岗位的情况，继续找下一级审批岗位
		 *//*
		int nextSeq = 1;
		int nextApprovalRoleLevel = 0;
		Role resultRole = null;
		if (nextSeq == 1) {
			nextApprovalRoleLevel = approvalRule.getOneApprovalRole();
			resultRole = getTempApprovalRoleId(requestRole,nextApprovalRoleLevel,approvalRule.getLowestApprovalRole());
			if(resultRole==null){
				nextSeq =2;
			}
		} 
		if (nextSeq == 2) {
			nextApprovalRoleLevel = approvalRule.getTwoApprovalRole();
			resultRole = getTempApprovalRoleId(requestRole,nextApprovalRoleLevel,approvalRule.getLowestApprovalRole());
			if(resultRole==null){
				nextSeq =3;
			}
		} 
		if (nextSeq == 3) {
			nextApprovalRoleLevel = approvalRule.getThreeApprovalRole();
			resultRole = getTempApprovalRoleId(requestRole,nextApprovalRoleLevel,approvalRule.getLowestApprovalRole());
			if(resultRole==null){
				nextSeq =4;
			}
		}
		if (nextSeq == 4) {
			nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
			resultRole = getTempApprovalRoleId(requestRole,nextApprovalRoleLevel,approvalRule.getLowestApprovalRole());
			if(resultRole==null){
				nextSeq =5;
			}
		} 
		if (nextSeq == 5) {
			nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
			resultRole = getTempApprovalRoleId(requestRole,nextApprovalRoleLevel,approvalRule.getLowestApprovalRole());
		}
		if(resultRole==null){
			throw new ResultFaultException("10_00005");
		}
		//新增审批记录
		ApprovalRecord approvalRecord=new ApprovalRecord();
		approvalRecord.setRetroactiveId(retroactive.getRetroactiveId());
		approvalRecord.setSep(nextSeq);
		approvalRecord.setIsApprove(1);
		approvalRecord.setRoleId(resultRole.getRoleId());
		record=approvalRecordDao.insertSelective(approvalRecord);
		if(record<=0){
			return false;
		}
		//取补签审批人信息List (邮件提醒)
		List<ApprovalRecordBean> arList = approvalService.getApprovalRecordById(retroactive.getRetroactiveId());
		String textPart = "员工："+employeeDao.selectByPrimaryKey(employeeId).getChineseName()
				+"补签申请待审批，请及时登陆HR考勤管理系统查看。";
		for (ApprovalRecordBean approvalRecordBean : arList) {
			String ids = approvalRecordBean.getApproverIds();
			String[] strIds=ids.split(",");
			for (int i = 0; i < strIds.length; i++) {
				approvalService.sendEmail(Integer.parseInt(strIds[i]), textPart, approvalRecordBean.getRetroactiveId(), 99);
			}
		}*/
		
		bpmService.openApplyBPM(null,retroactive, employeeId, "hr003");
		return true;
	}
	
	/*
	 * 通过申请人的岗位id，取审批人的岗位
	 * 找不到合适的岗位时，返回null
	 */
	private Role getTempApprovalRoleId(Role requestRole, Integer nextApprovalRoleLevel,Integer lowestApprovalLevel) {
		
		// 取所有父级岗位Id
		String rolePath = requestRole.getRolePath();
		String[] roleIds = reverseArray(rolePath.split("-"));
		List<Integer> roleIdList = new ArrayList<Integer>();
		for (String roleid : roleIds) {
			if(StringUtils.isEmpty(roleid)){
				continue;
			}
			int intRoleId = Integer.parseInt(roleid);
			//跳过岗位本身
			if(intRoleId == requestRole.getRoleId().intValue()){
				continue;
			}
			// 取N+1岗位id
			if (nextApprovalRoleLevel == 99) {
				Role pareRole = roleDao.selectByPrimaryKey(intRoleId);
				if(pareRole.getRoleLevel()<lowestApprovalLevel)
				{
					//不符合最低审批级别
					continue;
				}
				if(haveEmployeeInRole(intRoleId)){
					return pareRole;
				}else{
					//空岗位跳过
					continue;
				}
				
			}else{
				roleIdList.add(Integer.parseInt(roleid));	
			}
		}
		if (nextApprovalRoleLevel==99 || roleIdList.size()==0) {
			throw new ResultFaultException("10_00005");
		}
		// 取指定级别的审批人岗位
		RoleExample roleExample = new RoleExample();
		roleExample.createCriteria().andRoleLevelEqualTo(nextApprovalRoleLevel).andRoleIdIn(roleIdList);
		List<Role> roleList = roleDao.selectByExample(roleExample);
		if(roleList==null || roleList.size()==0){
			//没有当前级别的岗位
			return null;
		}
		//空岗位
		if(!haveEmployeeInRole(roleList.get(0).getRoleId())){
			return null;
		}
		return roleList.get(0);
	}
	
	/*
	 * 判断当前岗位是不是空岗位 
	 */
	private boolean haveEmployeeInRole(Integer roleId){
		EmployeeRoleExample example = new EmployeeRoleExample();
		example.or().andRoleIdEqualTo(roleId).andFromDateLessThanOrEqualTo(new Date()).andThruDateIsNull();
		example.or().andRoleIdEqualTo(roleId).andFromDateLessThanOrEqualTo(new Date()).andThruDateGreaterThanOrEqualTo(new Date());

		List<EmployeeRole> employeeRoleList = employeeRoleDao.selectByExample(example);
		if(employeeRoleList==null || employeeRoleList.size()==0){
			return false;
		}
		List<Integer> employeeIds = new ArrayList<Integer>();
		for (EmployeeRole employeeRole : employeeRoleList) {
			employeeIds.add(employeeRole.getEmployeeId());
		}
		EmployeeExample employeeExample = new EmployeeExample();
		EmployeeExample.Criteria employeeCriteria = employeeExample.createCriteria();
		employeeCriteria.andEmployeeIdIn(employeeIds);
		employeeCriteria.andIsDisabledEqualTo(0);
		List<Employee> employeeList = employeeDao.selectByExample(employeeExample);
		if(employeeList==null || employeeList.size()==0){
			return false;
		}
		return true;
	}
	
	private ApprovalRule getApprovalRule(Role requestRole){
		
		//取得所有审批规则
		ApprovalRuleExample approvalRuleExample=new ApprovalRuleExample();
		approvalRuleExample.createCriteria().andRequestTypeEqualTo(14);
		List<ApprovalRule> approvalRuleList = approvalRuleDao.selectByExample(new ApprovalRuleExample());
		for (ApprovalRule approvalRule : approvalRuleList) {
			if(approvalRule.getRequestType() == 14){//暂时，补签类型写死14
				if(approvalRule.getRequestRole() == 99 || approvalRule.getRequestRole()==requestRole.getRoleLevel()){
					return approvalRule;
				}
			}
		}
		return null;
	}
	
    /* 
     * 函数：reverseArray  
     * 功能：实现 数组翻转 
     * 例如：{'a','b','c','d'}变成{'d','c','b','a'} 
     */  
    private String[] reverseArray(String[] Array) {  
        String[] new_array = new String[Array.length];  
        for (int i = 0; i < Array.length; i++) {  
            // 反转后数组的第一个元素等于源数组的最后一个元素：  
            new_array[i] = Array[Array.length - i - 1];  
        }  
        return new_array;  
    }
	

	/**
	 * 查询用户考勤补签信息
	 */
	@Override
	public RetroactivePageBean getRetroactiveList(Integer employeeId, Date attendanceDateStart,
			Date attendanceDateEnd, Integer startNum, Integer pageCount) {
		RetroactivePageBean retroactivePageBean=new RetroactivePageBean();
		List<RetroactiveBean> retroctiveBeanList = retroactiveExtDao.getRetroactiveList(employeeId, attendanceDateStart, attendanceDateEnd, startNum, pageCount);
		retroactivePageBean.setRetroctiveBeanList(retroctiveBeanList);
		int pageTotal=retroactiveExtDao.countByRetroactiveBean(employeeId, attendanceDateStart, attendanceDateEnd);
		retroactivePageBean.setPageTotal(pageTotal);
		return retroactivePageBean;
	}

	/**
	 * 获取补签次数
	 */
	@Override
	public int getRetroactiveNum(Integer employeeId,Date attendanceDateStart, Date attendanceDateEnd) {
		int retroactiveNum=retroactiveExtDao.countByRetroactiveNum(employeeId,attendanceDateStart, attendanceDateEnd);
		return retroactiveNum;
	}
	
	/**
	 * 获取包括在申请中的补签次数
	 */
	@Override
	public int getRetroactiveNumAble(Integer employeeId,Date attendanceDateStart, Date attendanceDateEnd) {
		int retroactiveNum=retroactiveExtDao.countRetroactiveNumAble(employeeId,attendanceDateStart, attendanceDateEnd);
		return retroactiveNum;
	}
	
	
	/**
	 * 根据补签ID中的考勤ID，查询对应数据
	 * @param Retroactiveid
	 * @return
	 */
	@Override
	public Attendance getAttendanceByAttendanceId(Integer attendanceId){
		Attendance attendance=attendanceDao.selectByPrimaryKey(attendanceId);
		return attendance;
	}

	/**
	 * HR获取管理公司的补签信息
	 */
	@Override
	public RetroactivePageBean getRetroactiveListByHR(RetroactiveBean retroactiveBean) {
		RetroactivePageBean retroactivePageBean=new RetroactivePageBean();
		List<RetroactiveBean> retroctiveBeanList = retroactiveExtDao.getRetroactiveListByHR(retroactiveBean);
		retroactivePageBean.setRetroctiveBeanList(retroctiveBeanList);
		int pageTotal=retroactiveExtDao.countByHR(retroactiveBean);
		retroactivePageBean.setPageTotal(pageTotal);
		return retroactivePageBean;
	}

	/**
	 * 查看HR分配的公司
	 */
	@Override
	public RetroactiveBean getRetroactiveBeanByHR(RetroactiveBean retroactiveBean, Integer employeeId) {
		EmployeeCorporationExample example=new EmployeeCorporationExample();
		example.or().andEmployeeIdEqualTo(employeeId)
		.andIsCorporationEqualTo(1)
		.andFromDateLessThanOrEqualTo(new Date())
		.andThruDateGreaterThanOrEqualTo(new Date());
		
		example.or().andEmployeeIdEqualTo(employeeId)
		.andIsCorporationEqualTo(1)
		.andFromDateLessThanOrEqualTo(new Date())
		.andThruDateIsNull();
		
		List<EmployeeCorporation> list=employeeCorporationDao.selectByExample(example);
		if (list.size()>0) {
			// 公司code集合 
		 	List<String> corporationList=new ArrayList<>();
		 	//传参的公司code集合
		 	List<String> corporationListRe=retroactiveBean.getCorporationList();
			for (EmployeeCorporation employeeCorporation : list) {
				Integer corporationId=employeeCorporation.getCorporationId();
				Corporation corporation=corporationDao.selectByPrimaryKey(corporationId);
				if (corporationListRe!=null && corporationListRe.size()>0) {
					for (String corporationCode : corporationListRe) {
						if (corporationCode.equals(corporation.getCorporationCode())) {
							corporationList.add(corporation.getCorporationCode());
						}
					}
					if (corporationList.size()==0) {
						retroactiveBean.setCorporationId(-1);
					}
				} else {//参数为空的情况
					corporationList.add(corporation.getCorporationCode());
				}
			}
			retroactiveBean.setCorporationList(corporationList);
		} else {//hrbp没有分配公司的情况
			retroactiveBean.setCorporationId(-1);
		}
		return retroactiveBean;
	}
	/**
	 * 一键补签
	 */
	@Override
	public boolean saveOnceRetroactive(RetroactiveBean retroacticeBean) {
		Integer employeeId=retroacticeBean.getEmployeeId();
		Date rDate=retroacticeBean.getAttendanceDate();
		AttendanceExample attendanceExample=new AttendanceExample();
		attendanceExample.createCriteria().andAttendanceDateEqualTo(rDate)
		.andEmployeeIdEqualTo(employeeId);
		List<Attendance> attendanceList=attendanceDao.selectByExample(attendanceExample);
		if(attendanceList.size()>0){
			Attendance attendance=attendanceList.get(0);
			Integer attendanceId=attendance.getAttendanceId();
			//补签是否重复
			List<Integer> approvalStateList=new ArrayList<>();
			approvalStateList.add(1);
			approvalStateList.add(2);
			if (retroacticeBean.getStartTime()!=null) {
				RetroactiveExample retroactiveExample=new RetroactiveExample();
				retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceId)
				.andApprovalStateIn(approvalStateList)
				.andStartTimeIsNotNull();
				List<Retroactive> rList=retroactiveDao.selectByExample(retroactiveExample);
				if (rList.size()>0) {
					throw new ResultFaultException("2_00003");
				}
			} else if(retroacticeBean.getEndTime()!=null){
				RetroactiveExample retroactiveExample=new RetroactiveExample();
				retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceId)
				.andApprovalStateIn(approvalStateList)
				.andEndTimeIsNotNull();
				List<Retroactive> rList=retroactiveDao.selectByExample(retroactiveExample);
				if (rList.size()>0) {
					throw new ResultFaultException("2_00003");
				}
			}
			//新增补签信息
			retroacticeBean.setAttendanceId(attendance.getAttendanceId());
			saveRetroactive(retroacticeBean, employeeId);
		} else {
			//创建考勤信息，插入数据库
			Attendance newAttendance=new Attendance();
			newAttendance.setEmployeeId(employeeId);
			newAttendance.setAttendanceDate(rDate);
			//判断是否为休假日，为休假日是9，不为休假日是5
			EmployeeSchedulExample employeeSchedulExample=new EmployeeSchedulExample();
			employeeSchedulExample.setOrderByClause("sw_id desc");
			employeeSchedulExample.createCriteria().andEmployeeIdEqualTo(employeeId)
			.andFromDateLessThanOrEqualTo(rDate)
			.andThruDateGreaterThanOrEqualTo(rDate);
			List<EmployeeSchedul> employeeSchedulList=employeeSchedulDao.selectByExample(employeeSchedulExample);
			if(employeeSchedulList.size()>0){
				Integer swId=employeeSchedulList.get(0).getSwId();
				SchedulDayExample schedulDayExample=new SchedulDayExample();
				schedulDayExample.createCriteria().andSdDateEqualTo(rDate)
				.andSwIdEqualTo(swId);
				List<SchedulDayKey> sdList=schedulDayDao.selectByExample(schedulDayExample);
				if(sdList.size()>0){
					Integer punchTimeId=employeeSchedulList.get(0).getPunchTimeId();
					PunchTime punchTime=punchTimeDao.selectByPrimaryKey(punchTimeId);
					newAttendance.setAttendenceHours(new BigDecimal(punchTime.getHours()/60));
					newAttendance.setAttendanceState(5);
				}else {
					newAttendance.setAttendanceState(9);
				}
				newAttendance.setIsApprovaled(0);
				newAttendance.setIsRepaired(0);
				int record=attendanceDao.insertSelective(newAttendance);
				if(record<=0) {
					return false;
				}
				retroacticeBean.setAttendanceId(newAttendance.getAttendanceId());
				this.saveRetroactive(retroacticeBean, employeeId);
			} else {
				//未找到排班
			}
		}
		return true;
	}

	/**
	 * 跨天补签
	 */
	@Override
	public boolean saveAcrossRetroactive(RetroactiveBean retroactiveBean) {
		Integer employeeId = retroactiveBean.getEmployeeId();
		if (retroactiveBean.getEndTime()!=null) { //保存第一天补签
			RetroactiveBean firstRetro = new RetroactiveBean();
			firstRetro.setEmployeeId(employeeId);
			firstRetro.setRoleId(retroactiveBean.getRoleId());
			firstRetro.setAttendanceDate(retroactiveBean.getFirstDate());
			firstRetro.setEndTime(retroactiveBean.getEndTime());
			firstRetro.setDescription(retroactiveBean.getDescription());
			firstRetro.setZeroDegree(0);
			if (!this.saveOnceRetroactive(firstRetro)) {
				return false;
			}
		}
		
		if (retroactiveBean.getStartTime()!=null) { //保存第二天补签
			RetroactiveBean secondRetro = new RetroactiveBean();
			secondRetro.setEmployeeId(employeeId);
			secondRetro.setRoleId(retroactiveBean.getRoleId());
			secondRetro.setAttendanceDate(DateUtils.addDays(retroactiveBean.getFirstDate(), 1));
			secondRetro.setStartTime(retroactiveBean.getStartTime());
			secondRetro.setDescription(retroactiveBean.getDescription());
			secondRetro.setZeroDegree(0);
			if (!this.saveOnceRetroactive(secondRetro)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 获取某天能撤回的补签申请List
	 */
	@Override
	public List<RetroactiveBean> getRetroactives(RetroactiveBean retroactiveBean) {
		List<RetroactiveBean> rbList = retroactiveExtDao.getRetroactives(retroactiveBean.getAttendanceDate(), retroactiveBean.getEmployeeId());
		
		return rbList;
	}
	
	/**
	 * 验证同一个时间，补签是否重复
	 * true 重复，false不重复
	 */
	private boolean verifyRetroactive(RetroactiveBean retroactiveBean, Integer employeeId) {
		//审批状态[1,2]
		List<Integer> stateList = new ArrayList<>();
		stateList.add(1);
		stateList.add(2);
		RetroactiveExample rExample = new RetroactiveExample();
		com.attendance.www.hr.entitys.RetroactiveExample.Criteria criteria = rExample.createCriteria();
		criteria.andEmployeeIdEqualTo(employeeId)
		.andAttendanceIdEqualTo(retroactiveBean.getAttendanceId())
		.andApprovalStateIn(stateList);
		if (retroactiveBean.getStartTime()!=null) {
			criteria.andStartTimeIsNotNull();
		} else {
			criteria.andEndTimeIsNotNull();
		}
		List<Retroactive> reList = retroactiveDao.selectByExample(rExample);
		if (reList.size()>0) {
			return true;
		}
		return false;
	}
}
